home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH25 / IMGPRCS6.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-08-05  |  7.1 KB  |  336 lines

  1. ; IMGPRCS.ASM
  2. ;
  3. ; An image processing program (Second optimization pass).
  4. ;
  5. ; This program blurs an eight-bit grayscale image by averaging a pixel
  6. ; in the image with the eight pixels around it.  The average is computed
  7. ; by (CurCell*8 + other 8 cells)/16, weighting the current cell by 50%.
  8. ;
  9. ; Because of the size of the image (almost 64K), the input and output
  10. ; matrices are in different segments.
  11. ;
  12. ; Version #1: Straight-forward translation from Pascal to Assembly.
  13. ;
  14. ; Version #2: Three major optimizations. (1) used movsd instruction rather
  15. ;          than a loop to copy data from DataOut back to DataIn.
  16. ;          (2) Used repeat..until forms for all loops.  (3) unrolled
  17. ;          the innermost two loops (which is responsible for most of
  18. ;          the performance improvement).
  19. ;
  20. ; Version #3: Used registers for all variables. Set up segment registers
  21. ;          once and for all through the execution of the main loop so
  22. ;          the code didn't have to reload ds each time through.  Computed
  23. ;          index into each row only once (outside the j loop).
  24. ;
  25. ; Version #4: Eliminated copying data from DataOut to DataIn on each pass.
  26. ;          Removed hazards.  Maintained common subexpressions. Did some
  27. ;          more loop unrolling.
  28. ;
  29. ; Version #6: Changed the blurring algorithm to use fewer computations.
  30. ;          This version does *NOT* produce the same data as the other
  31. ;          programs.
  32. ;
  33. ;
  34. ;    Performance comparisons (66 MHz 80486 DX/2 system).
  35. ;
  36. ;    This code-           2.2 seconds.
  37. ;    3rd optmization pass-  2.5 seconds.
  38. ;    2nd optimization pass-     4 seconds.
  39. ;    1st optimization pass-     6 seconds.
  40. ;    Original ASM code-    36 seconds.
  41. ;    Borland Pascal v7.0-    45 seconds.
  42. ;    Borland C++ v4.02-    29 seconds.
  43. ;    Microsoft C++ v8.00-    21 seconds.
  44.  
  45.         .xlist
  46.         include     stdlib.a
  47.         includelib    stdlib.lib
  48.         .list
  49.         .386
  50.         option        segment:use16
  51.  
  52.  
  53.  
  54. dseg        segment    para public 'data'
  55. InName        byte    "roller1.raw",0
  56. OutName        byte    "roller3.raw",0
  57. dseg        ends
  58.  
  59.  
  60. ; Here is the input data that we operate on.
  61.  
  62. InSeg        segment    para public 'indata'
  63.  
  64. DataIn        byte    251 dup (256 dup (?))
  65.  
  66. InSeg        ends
  67.  
  68.  
  69. ; Here is the output array that holds the result.
  70.  
  71. OutSeg        segment    para public 'outdata'
  72.  
  73. DataOut        byte    251 dup (256 dup (?))
  74.  
  75. OutSeg        ends
  76.  
  77.  
  78.  
  79.  
  80. cseg        segment    para public 'code'
  81.         assume    cs:cseg, ds:dseg
  82.  
  83. Main        proc
  84.         mov    ax, dseg
  85.         mov    ds, ax
  86.         meminit
  87.  
  88.         mov    ax, 3d00h    ;Open input file for reading.
  89.         lea    dx, InName
  90.         int    21h
  91.         jnc    GoodOpen
  92.         print
  93.         byte    "Could not open input file.",cr,lf,0
  94.         jmp    Quit
  95.  
  96. ; Optimization modification- read the data into DataOut rather than
  97. ; DataIn because we'll move it into DataIn at the beginning of the
  98. ; h loop.
  99.  
  100. GoodOpen:    mov    bx, ax        ;File handle.
  101.         mov    dx, InSeg    ;Where to put the data.
  102.         mov    ds, dx
  103.         lea    dx, DataIn
  104.         mov    cx, 256*251    ;Size of data file to read.
  105.         mov    ah, 3Fh
  106.         int    21h
  107.         cmp    ax, 256*251    ;See if we read the data.
  108.         je    GoodRead
  109.         print
  110.         byte    "Did not read the file properly",cr,lf,0
  111.         jmp    Quit
  112.  
  113. GoodRead:       print
  114.         byte    "Enter number of iterations: ",0
  115.         getsm
  116.         atoi
  117.         free
  118.         mov    bp, ax
  119.         cmp    ax, 0
  120.         jle    Quit
  121.  
  122.         print
  123.         byte    "Computing Result",cr,lf,0
  124.  
  125.  
  126.         assume    ds:InSeg, es:OutSeg
  127.  
  128.         mov    ax, InSeg
  129.         mov    ds, ax
  130.         mov    ax, OutSeg
  131.         mov    es, ax
  132.  
  133. ; Copy the data once so we get the edges in both arrays.
  134.  
  135.         mov    cx, (251*256)/4
  136.         lea    si, DataIn
  137.         lea    di, DataOut
  138.     rep    movsd
  139.  
  140.  
  141. ; "hloop" repeats once for each iteration.
  142.  
  143. hloop:
  144.         mov    ax, InSeg
  145.         mov    ds, ax
  146.         mov    ax, OutSeg
  147.         mov    es, ax
  148.  
  149. ; "iloop" processes the rows in the matrices.
  150.  
  151.         mov    cl, 249
  152. iloop:        mov    bh, cl            ;i*256
  153.         mov    bl, 1            ;Start at j=1.
  154.         mov    ch, 254/2        ;# of times through loop.
  155.         mov    si, bx
  156.         mov    dh, 0            ;Compute sum here.
  157.         mov    bh, 0
  158.         mov    ah, 0
  159.  
  160. ; "jloop" processes the individual elements of the array.
  161. ; This loop has been unrolled once to allow the two portions to share
  162. ; some common computations.
  163.  
  164. jloop:
  165.  
  166. ; The sum of DataIn [i-1][j] + DataIn[i-1][j+1] + DataIn[i+1][j] +
  167. ; DataIn [i+1][j+1] will be used in the second half of this computation.
  168. ; So save its value in a register (di) until we need it again.
  169.  
  170.         mov    dl, DataIn[si]        ;[i,j]
  171.         mov    al, DataIn[si-256]    ;[I-1,j]
  172.         shl    dx, 2            ;[i,j]*4
  173.         mov    bl, DataIn[si-1]    ;[i,j-1]
  174.         add    dx, ax
  175.         mov    al, DataIn[si+1]    ;[i,j+1]
  176.         add    dx, bx
  177.         mov    bl, DataIn[si+256]    ;[i+1,j]
  178.         add    dx, ax
  179.         shl    ax, 2            ;[i,j+1]*4
  180.         add    dx, bx
  181.         mov    bl, DataIn[si-255]    ;[i-1,j+1]
  182.         shr    dx, 3            ;Divide by 8.
  183.         add    ax, bx
  184.         mov    DataOut[si], dl
  185.         mov    bl, DataIn[si+2]    ;[i,j+2]
  186.         mov    dl, DataIn[si+257]    ;[i+1,j+1]
  187.         add    ax, bx
  188.         mov    bl, DataIn[si]        ;[i,j]
  189.         add    ax, dx
  190.         add    ax, bx
  191.         shr    ax, 3
  192.         dec    ch
  193.         mov    DataOut[si+1], al
  194.         jne    jloop
  195.  
  196.         dec    cl
  197.         jne    iloop
  198.  
  199.         dec    bp
  200.         je    Done
  201.  
  202.  
  203. ; Special case so we don't have to move the data between the two arrays.
  204. ; This is an unrolled version of the hloop that swaps the input and output
  205. ; arrays so we don't have to move data around in memory.
  206.  
  207.         mov    ax, OutSeg
  208.         mov    ds, ax
  209.         mov    ax, InSeg
  210.         mov    es, ax
  211.         assume    es:InSeg, ds:OutSeg
  212.  
  213. hloop2:
  214.  
  215.         mov    cl, 249
  216. iloop2:        mov    bh, cl
  217.         mov    bl, 1
  218.         mov    ch, 254/2
  219.         mov    si, bx
  220.         mov    dh, 0
  221.         mov    bh, 0
  222.         mov    ah, 0
  223. jloop2:
  224.         mov    dl, DataOut[si-256]
  225.         mov    al, DataOut[si-255]
  226.         mov    bl, DataOut[si+257]
  227.         add    dx, ax
  228.         mov    al, DataOut[si+256]
  229.         add    dx, bx
  230.         mov    bl, DataOut[si+1]
  231.         add    dx, ax
  232.         mov    al, DataOut[si+255]
  233.  
  234.         mov    di, dx
  235.  
  236.         add    dx, bx
  237.         mov    bl, DataOut[si-1]
  238.         add    dx, ax
  239.         mov    al, DataOut[si]
  240.         add    dx, bx
  241.         mov    bl, DataOut[si-257]
  242.         shl    ax, 3
  243.         add    dx, bx
  244.         add    dx, ax
  245.         shr    ax, 3
  246.         shr    dx, 4
  247.         mov    DataIn[si], dl
  248.  
  249.         mov    dx, di
  250.         mov    bl, DataOut[si-254]
  251.         add    dx, ax
  252.         mov    al, DataOut[si+2]
  253.         add    dx, bx
  254.         mov    bl, DataOut[si+258]
  255.         add    dx, ax
  256.         mov    al, DataOut[si+1]
  257.         add    dx, bx
  258.         shl    ax, 3
  259.         add    si, 2
  260.         add    dx, ax
  261.         mov    ah, 0
  262.         shr    dx, 4
  263.         dec    ch
  264.         mov    DataIn[si-1], dl
  265.         jne    jloop2
  266.  
  267.         dec    cl
  268.         jne    iloop2
  269.  
  270.         dec    bp
  271.         je    Done2
  272.         jmp    hloop
  273.  
  274.  
  275. ; Kludge to guarantee that the data always resides in the output segment.
  276.  
  277. Done2:
  278.         mov    ax, InSeg
  279.         mov    ds, ax
  280.         mov    ax, OutSeg
  281.         mov    es, ax
  282.         mov    cx, (251*256)/4
  283.         lea    si, DataIn
  284.         lea    di, DataOut
  285.     rep    movsd
  286.  
  287. Done:        print
  288.         byte    "Writing result",cr,lf,0
  289.  
  290.  
  291. ; Okay, write the data to the output file:
  292.  
  293.         mov    ah, 3ch        ;Create output file.
  294.         mov    cx, 0        ;Normal file attributes.
  295.         mov    dx, dseg
  296.         mov    ds, dx
  297.         lea    dx, OutName
  298.         int    21h
  299.         jnc    GoodCreate
  300.         print
  301.         byte    "Could not create output file.",cr,lf,0
  302.         jmp    Quit
  303.  
  304. GoodCreate:    mov    bx, ax        ;File handle.
  305.         push    bx
  306.         mov    dx, OutSeg    ;Where the data can be found.
  307.         mov    ds, dx
  308.         lea    dx, DataOut
  309.         mov    cx, 256*251    ;Size of data file to write.
  310.         mov    ah, 40h        ;Write operation.
  311.         int    21h
  312.         pop    bx        ;Retrieve handle for close.
  313.         cmp    ax, 256*251    ;See if we wrote the data.
  314.         je    GoodWrite
  315.         print
  316.         byte    "Did not write the file properly",cr,lf,0
  317.         jmp    Quit
  318.  
  319. GoodWrite:    mov    ah, 3eh        ;Close operation.
  320.         int    21h
  321.  
  322.  
  323. Quit:        ExitPgm            ;DOS macro to quit program.
  324. Main        endp
  325.  
  326. cseg        ends
  327.  
  328. sseg        segment    para stack 'stack'
  329. stk        byte    1024 dup ("stack   ")
  330. sseg        ends
  331.  
  332. zzzzzzseg    segment    para public 'zzzzzz'
  333. LastBytes    byte    16 dup (?)
  334. zzzzzzseg    ends
  335.         end    Main
  336.